import socket, wx, threading
from concurrent.futures import ThreadPoolExecutor  # 线程池的管理


class Server(wx.Frame):

    def __init__(self):
        # 实例属性
        self.isOn = False
        self.server_socket = socket.socket()
        # 绑定ip和端口号
        self.server_socket.bind(('0.0.0.0', 8998))
        # 设置监听
        self.server_socket.listen(5)
        # 保存所有客户线程
        self.client_thread_dict = {}
        # 创建线程池
        self.pool = ThreadPoolExecutor(max_workers=10)

        wx.Frame.__init__(self, None, title="服务端", size=(500, 600), pos=(200, 200))
        self.pl = wx.Panel(self, size=(500, 600), pos=(0, 0))
        # 启动服务器
        btn_start = wx.Button(self.pl, label="开启服务端", pos=(30, 10), size=(150, 30))
        # 保存聊天记录
        btn_save = wx.Button(self.pl, label="保存聊天记录", pos=(300, 10), size=(150, 30))
        # 接收消息的文本框
        self.recv_text = wx.TextCtrl(self.pl, pos=(0, 60), size=(500, 200), style=wx.TE_READONLY | wx.TE_MULTILINE)
        self.Bind(wx.EVT_BUTTON, self.start, btn_start)
        self.Bind(wx.EVT_BUTTON, self.save, btn_save)

    def start(self, event):
        if not self.isOn:
            self.isOn = True
            print("lalala")
            # 创建线程
            main_thread = threading.Thread(target=self.main_thread_fun)
            # 设置守护线程
            main_thread.daemon = True
            # 启动线程
            main_thread.start()

    def main_thread_fun(self):
        # 等待客户端连接
        while self.isOn:
            conn, addr = self.server_socket.accept()
            client_name = conn.recv(1024).decode("utf8")
            client_thread = ClientThread(self, conn, client_name)
            self.client_thread_dict[client_name] = client_thread
            self.pool.submit(client_thread.run)
            self.send(f"欢迎{client_name}加入聊天室")

    def send(self, mes):
        self.recv_text.AppendText(mes+"\n")
        for client in self.client_thread_dict.values():
            if client.isOn:
                client.conn.send(mes.encode("utf8"))

    def save(self, event):
        record = self.recv_text.GetValue()
        with open("record.log", "a+", encoding="GBK") as f:
            f.write(record)


class ClientThread(threading.Thread):
    def __init__(self, server , conn, client_name):
        threading.Thread.__init__(self)
        self.server = server
        self.conn = conn
        self.client_name = client_name
        self.isOn = True

    def run(self):
        while self.isOn:
            text = self.conn.recv(2024).decode("utf8")
            if text == "断开连接":
                self.isOn = False
                self.server.send(f"{self.client_name}已经退出聊天室")
            else:
                self.server.send(f"{self.client_name}: {text}")
        self.conn.close()


# 程序入口
if __name__ == '__main__':
    app = wx.App()
    server = Server()
    server.Show()

    app.MainLoop()
